package com.diandian.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * @description HttpUtils
 * @author TDW
 * @date 2018年6月14日
 *
 */
public abstract class HttpUtils {

	private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);

	/**
	 * 读取超时
	 */
	private static final int READ_TIMEOUT = 1000 * 3;
	/**
	 * 链接超时
	 */
	private static final int CONNECT_TIMEOUT = 1000 * 5;

	/**
	 * @description doGet charset utf-8
	 * @param url
	 * @return
	 * @throws IOException
	 * @author TDW
	 * @date 2018年6月14日
	 * @modify_date
	 * @modify_author
	 * @modify_desc
	 */
	public static List<String> doGet(String url) throws IOException {
		return doGet(url, "utf-8", "utf-8");
	}

	/**
	 * @description doPost
	 * @param url
	 * @return
	 * @throws IOException
	 * @author TDW
	 * @date 2018年6月14日
	 * @modify_date
	 * @modify_author
	 * @modify_desc
	 */
	public static List<String> doPost(String url) throws IOException {
		return doGet(url, "utf-8", "utf-8");
	}

	/**
	 * @description doGet
	 * @param url
	 * @param requestCharset
	 * @param receiveCharset
	 * @return
	 * @throws IOException
	 * @author TDW
	 * @date 2018年6月14日
	 * @modify_date
	 * @modify_author
	 * @modify_desc
	 */
	public static List<String> doGet(String url, String requestCharset, String receiveCharset) throws IOException {
		if (StringUtils.isBlank(url)) {
			return null;
		}
		requestCharset = StringUtils.isEmpty(requestCharset) ? "utf-8" : requestCharset;
		receiveCharset = StringUtils.isEmpty(receiveCharset) ? "utf-8" : receiveCharset;

		List<String> result = null;
		HttpURLConnection connection = null;
		try {
			LOGGER.info("开始调用url=" + url);
			connection = getConnection(url, requestCharset);
			connection.setRequestMethod("GET");
			result = getContent(connection.getInputStream(), receiveCharset);
		} catch (Exception e) {
			LOGGER.error("调用url=" + url + "时发生错误", e);
		} finally {
			if (connection != null) {
				connection.disconnect();
			}
		}
		return result;
	}

	/**
	 * @description doPost
	 * @param url
	 * @param requestCharset
	 * @param receiveCharset
	 * @return
	 * @throws IOException
	 * @author TDW
	 * @date 2018年6月14日
	 * @modify_date
	 * @modify_author
	 * @modify_desc
	 */
	public static List<String> doPost(String url, String requestCharset, String receiveCharset) throws IOException {
		if (StringUtils.isBlank(url)) {
			return null;
		}
		requestCharset = StringUtils.isEmpty(requestCharset) ? "utf-8" : requestCharset;
		receiveCharset = StringUtils.isEmpty(receiveCharset) ? "utf-8" : receiveCharset;

		List<String> result = null;
		HttpURLConnection connection = null;
		try {
			LOGGER.info("开始调用url=" + url);
			connection = getConnection(url, requestCharset);
			connection.setRequestMethod("POST");
			result = getContent(connection.getInputStream(), receiveCharset);
		} catch (Exception e) {
			LOGGER.error("调用url=" + url + "时发生错误", e);
		} finally {
			if (connection != null) {
				connection.disconnect();
			}
		}
		return result;
	}
	
	
	/**
	 * @description doPost
	 * @param URL
	 * @param paraMap
	 * @return
	 * @author TDW
	 * @date 2018年6月14日
	 * @modify_date 
	 * @modify_author
	 * @modify_desc
	 */
	public static String doPost(String URL, Map<String, String> paraMap) {
		LOGGER.info("{}开始调用{},paraMap={}",URL,paraMap);
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(READ_TIMEOUT)
				.setConnectTimeout(CONNECT_TIMEOUT).build();
		CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
		HttpPost post = new HttpPost(URL);
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		for (Entry<String, String> entry : paraMap.entrySet()) {
			nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
		}
		CloseableHttpResponse response = null;
		String result = null;
		try {
			post.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
			response = httpClient.execute(post);
			int statecode = response.getStatusLine().getStatusCode();
			if (statecode == 200) {
				HttpEntity httpentity = response.getEntity();
				if (httpentity != null) {
					// 服务器返回的JSON字符串，建议要当做日志记录起来
					result = EntityUtils.toString(httpentity);
				}
			}
		} catch (Exception e) {
			LOGGER.error("调用url{}失败",URL,e);
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				LOGGER.error("关闭失败",e);
			}
			try {
				post.abort();
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				httpClient.close();
			} catch (IOException e) {
				LOGGER.error("关闭失败",e);
			}
		}
		return result;

	}

	
	/**
	 * @description doPost
	 * @param URL
	 * @param paraMap
	 * @param CONNECT_TIMEOUT
	 * @param READ_TIMEOUT
	 * @return
	 * @author TDW
	 * @date 2018年6月27日
	 * @modify_date 
	 * @modify_author
	 * @modify_desc
	 */
	public static String doPost(String URL, Map<String, String> paraMap,int CONNECT_TIMEOUT,int READ_TIMEOUT) {
		//uuid作为调用跟踪,方便抓取相关日志
		String uuid = UUID.randomUUID().toString();
		LOGGER.info("{}开始调用{},paraMap={}",URL,paraMap);
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(READ_TIMEOUT)
				.setConnectTimeout(CONNECT_TIMEOUT).build();
		CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
		HttpPost post = new HttpPost(URL);
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		for (Entry<String, String> entry : paraMap.entrySet()) {
			nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
		}
		CloseableHttpResponse response = null;
		String result = null;
		try {
			post.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
			response = httpClient.execute(post);
			int statecode = response.getStatusLine().getStatusCode();
			if (statecode == 200) {
				HttpEntity httpentity = response.getEntity();
				if (httpentity != null) {
					// 服务器返回的JSON字符串，建议要当做日志记录起来
					result = EntityUtils.toString(httpentity);
					if(result !=null){
						result = result.replaceAll("[\\t\\n\\r]", "");
					}
				}
			}
		} catch (Exception e) {
			LOGGER.error(uuid+"调用url{}失败",URL,e);
		} finally {
			try {
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				LOGGER.error("关闭失败",e);
			}
			try {
				post.abort();
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				httpClient.close();
			} catch (IOException e) {
				LOGGER.error("关闭失败",e);
			}
		}
		return result;

	}

	
	
	
	/**
	 * @description getConnection 获取http链接
	 * @param url
	 * @param charset
	 * @return
	 * @throws IOException
	 * @author TDW
	 * @date 2018年6月14日
	 * @modify_date
	 * @modify_author
	 * @modify_desc
	 */
	private static HttpURLConnection getConnection(String url, String charset) throws IOException {
		charset = StringUtils.isEmpty(charset) ? "utf-8" : charset;

		URL initUrl = new URL(url);
		HttpURLConnection connection = (HttpURLConnection) initUrl.openConnection();
		connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);
		connection.setReadTimeout(READ_TIMEOUT);
		connection.setConnectTimeout(CONNECT_TIMEOUT);
		// connection.setRequestProperty("Connection", "Keep-Alive");
		connection.connect();
		return connection;
	}


	/**
	 * @description getContent
	 * @param is
	 * @param charset
	 * @return
	 * @throws IOException
	 * @author TDW
	 * @date 2018年6月14日
	 * @modify_date
	 * @modify_author
	 * @modify_desc
	 */
	private static List<String> getContent(InputStream is, String charset) throws IOException {
		if (is == null) {
			return null;
		}
		charset = StringUtils.isEmpty(charset) ? "utf-8" : charset;

		List<String> result = new ArrayList<String>();
		BufferedReader buffer = null;
		try {
			buffer = new BufferedReader(new InputStreamReader(is, charset));
			String response;
			while ((response = buffer.readLine()) != null) {
				result.add(response);
			}
			return result;
		} finally {
			buffer.close();
		}
	}

	public static String toString(List<String> list) {
		StringBuilder result = new StringBuilder();
		int size = (list != null) ? list.size() : 0;
		for (int i = 0; i < size; i++) {
			result.append(list.get(i));
		}
		return result.toString();
	}

}
